package com.tasks.tablemodel;

import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
import org.apache.log4j.Logger;
import com.tasks.server.Column;
import com.tasks.server.DateTime;
import com.tasks.server.Executor;
import com.tasks.server.Server;
import com.tasks.server.ServerException;
import com.tasks.server.Table;
import com.tasks.table.Task;

public class DefaultTableModel extends AbstractTableModel {
	
	static Logger logger = Logger.getLogger(DefaultTableModel.class);
	private static final long serialVersionUID 	= -3849002076409084249L;
	
	private Object[][] contents;
    private String[] columnNames;
    private Class<?>[] columnClasses;

	public DefaultTableModel() {
	}
	
	public void set(Server s, Class<?> classType, String sql)
	{
        ArrayList<String> colNamesList = new ArrayList<String>();
        ArrayList<Class<?>> colClassesList = new ArrayList<Class<?>>();
        
        Column c[] =  Task.getColumns();
        
        colNamesList.add("TASKID");
        colClassesList.add (Integer.class);
        
        for(int i=0; i<c.length; i++)
        {
        	colNamesList.add(c[i].getColumnName());
        	
			switch (c[i].getDataType()) 
			{
				case Column.TABLE:
					colClassesList.add (Table.class); break;
				case Column.ENUM:
					colClassesList.add (Enum.class); break;
				case Column.INTEGER:
					colClassesList.add (Integer.class); break;
				case Column.DATETIME:
					colClassesList.add (DateTime.class); break;
				default:
					colClassesList.add (String.class); break;
			};
        }
        
        colNamesList.add("DTCREATED");
        colClassesList.add (DateTime.class);
        colNamesList.add("DTMODIFIED");
        colClassesList.add (DateTime.class);
        colNamesList.add("ROWVER");
        colClassesList.add (Integer.class);
        
        columnNames = new String [colNamesList.size()];
        colNamesList.toArray (columnNames);
        columnClasses = new Class [colClassesList.size()];
        colClassesList.toArray (columnClasses);

        ArrayList<Object[]> rowList = new ArrayList<Object[]>();
        
        Executor executor = new Executor(s);
        executor.execute(sql);
        
        try
        {
	        while (executor.next()) 
	        {
	            ArrayList<Object> cellList = new ArrayList<Object>();
	            for (int i = 0; i<columnClasses.length; i++) {
	                Object cellValue = null;
	                if (columnClasses[i] == String.class)
	                {
	                	cellValue = executor.getString(columnNames[i]);
	                }	                    
	                else if (columnClasses[i] == Integer.class)
	                {
	                    cellValue = executor.getInt(columnNames[i]);
	                }
	                else if (columnClasses[i] == DateTime.class)
	                {
	                    cellValue = executor.getDateTime((columnNames[i]));
	                }
	                else if (columnClasses[i] == Enum.class)
	                {
	                    cellValue = executor.getEnum((columnNames[i]));
	                }
	                else if (columnClasses[i] == Table.class)
	                {
	                	Class<?> ct = Table.getTableClass((columnNames[i]));
	        			try
	        			{
	        				cellValue = (Table) ct.getMethod("fetchById", new Class[]{Server.class, Integer.class}).invoke(null, new Object[]{s, new Integer(executor.getInt((columnNames[i])))});
	        			}
	        			catch (Exception e)
	        			{
	        				new ServerException(this, "addColumn", "Error invoking \"fetchById\" method of table " + classType.getCanonicalName());
	        			}
	                }
	                else
	                {
	                    System.out.println ("Can't assign " + columnNames[i]);
	                }
	                cellList.add(cellValue);
	            }
	            Object[] cells = cellList.toArray();
	            rowList.add(cells);
	        } 
        }
        catch (Exception ex)
        {
        	new ServerException(ex);
        }
        
        contents = new Object[rowList.size()] [];
        for (int i=0; i<contents.length; i++)
        {
        	contents[i] = (Object []) rowList.get (i);
        }
            
        System.out.println ("Created model with " + contents.length + " rows");
	}

	public int getColumnCount() {
		if (contents.length == 0)
            return 0;
        else
            return contents[0].length;
	}

	public int getRowCount() {
		return contents.length;
	}

	public Object getValueAt(int rowIndex, int columnIndex) {
		return contents [rowIndex][columnIndex];
	}
	
    // overrides of methods for which AbstractTableModel
    // has trivial implementatations
    public Class<?> getColumnClass (int col) {
        return columnClasses [col];
    }

    public String getColumnName (int col) {
        return columnNames [col];
    }
}
